#include "TileNode.hpp"
#include "PenroseBasedSamplerConstants.hpp"
#include "TemplUtilities.hpp"

TileNode::TileNode(TileNode *pParentNode, int iChildNum, Tile newTile) : Tile(newTile)
{
	m_pParentNode  = pParentNode;
	m_iChildNumber = iChildNum;
	m_bLeafNode    = true;

	m_childrenNodes.clear();
}

TileNode::TileNode(unsigned int iWidth, unsigned int iHeight) : Tile()
{
	m_pParentNode  = NULL;
	m_iChildNumber = 0;
	//m_bLeafNode    = true;

	double side  = getMax(iWidth, iHeight);
	double scale = 2.0 * side;	
	MVector2D offset(PHI*PHI/2.0 - 0.25, 0.125);
	offset = offset * scale;

	MTriangle triangle;
	triangle.setVertexA(offset);

	int iDir = 15;
	reCreateTile(TILE_F, iDir, scale, triangle);
}

TileNode::~TileNode()
{
	destroyBranch();
}

TileNode* TileNode::getNextNode()
{
	if(!m_bLeafNode)
		return m_childrenNodes[0];

	if(m_iDepthLevel == 0)
		return NULL;

	if(m_iChildNumber < m_pParentNode->getChildCount() - 1)
		return m_pParentNode->getChild(m_iChildNumber+1);

	TileNode* pTmp = this;
	do
	{
		pTmp = pTmp->getParent();

	} while((pTmp->getDepthLvl() != 0) && (pTmp->getChildNumber() == pTmp->getParent()->getChildCount() - 1));

	if(pTmp->getDepthLvl() == 0)
		return NULL;

	return pTmp->getParent()->getChild(pTmp->getChildNumber()+1);
}

TileNode* TileNode::getNextLeaf()
{
	TileNode* pTmp = this;

	do
	{
		pTmp = pTmp->getNextNode();

		if(!pTmp)
			return NULL;

		if(pTmp->isLeaf())
			return pTmp;

	} while(true);
}

TileNode* TileNode::getParent()
{
	return m_pParentNode;
}

TileNode* TileNode::getChild(size_t number)
{
	if(number >= getChildCount())
		return NULL;

	return m_childrenNodes[number];
}

bool TileNode::isLeaf()
{
	bool bSuccess = false;

	if(m_bLeafNode)
		bSuccess = true;

	return bSuccess;
}

unsigned int TileNode::getChildCount()
{
	return m_childrenNodes.size();
}

unsigned int TileNode::getDepthLvl()
{
	return m_iDepthLevel;
}

unsigned int TileNode::getChildNumber()
{
	return m_iChildNumber;
}

void TileNode::divide()
{
	if(!m_bLeafNode)
		return;

	m_bLeafNode = false;
	double newScale = getScale() / GOLDEN_RATIO;

	Tile* pTile = new Tile();
	switch(m_eType)
	{
	case TILE_A:
		pTile->setType(TILE_B);
		pTile->setDirection(getDir());
		pTile->setOrigin(MVector2D(getTriangle().getVertexA()));
		pTile->prePendToCode(B00);
		m_childrenNodes.push_back(new TileNode(this, 0, *pTile));
		break;

	case TILE_B:
		pTile->setType(TILE_A);
		pTile->setDirection(getDir()+10);
		pTile->setOrigin(MVector2D(getTriangle().getVertexA()));
		pTile->prePendToCode(B00);
		m_childrenNodes.push_back(new TileNode(this, 0, *pTile));
		break;

	case TILE_C:
		pTile->setType(TILE_F);
		pTile->setDirection(getDir() + 14);
		pTile->setOrigin(MVector2D(getTriangle().getVertexC()));
		pTile->prePendToCode(B00);
		m_childrenNodes.push_back(new TileNode(this, 0, *pTile));
		pTile->reset();

		pTile->setType(TILE_C);
		pTile->setScale(newScale);
		pTile->setDirection(getDir() + 6);
		pTile->setOrigin(getTriangle().getVertexB());
		pTile->prePendToCode(B10);
		m_childrenNodes.push_back(new TileNode(this, 1, *pTile));
		pTile->reset();

		pTile->setType(TILE_A);
		pTile->setScale(newScale);
		pTile->setDirection(getDir() + 1);
		pTile->setOrigin(m_childrenNodes[0]->getTriangle().getVertexC());
		pTile->prePendToCode(B10);
		m_childrenNodes.push_back(new TileNode(this, 2, *pTile));
		break;

	case TILE_D:
		pTile->setType(TILE_E);
		pTile->setDirection(getDir() + 6);
		pTile->setOrigin(getTriangle().getVertexB());
		pTile->prePendToCode(B00);
		m_childrenNodes.push_back(new TileNode(this, 0, *pTile));
		pTile->reset();

		pTile->setScale(newScale);
		pTile->setType(TILE_D);
		pTile->setDirection(getDir() + 14);
		pTile->setOrigin(m_childrenNodes[0]->getTriangle().getVertexC());
		pTile->prePendToCode(B10);
		m_childrenNodes.push_back(new TileNode(this, 1, *pTile));
		pTile->reset();
		break;

	case TILE_E:
		pTile->setType(TILE_C);
		pTile->setDirection(getDir() + 12);
		pTile->setOrigin(getTriangle().getVertexC());
		pTile->prePendToCode(B10);
		m_childrenNodes.push_back(new TileNode(this, 0, *pTile));
		pTile->reset();

		pTile->setScale(newScale);
		pTile->setType(TILE_E);
		pTile->setDirection(getDir() + 8);
		pTile->setOrigin(getTriangle().getVertexB());
		pTile->prePendToCode(B01);
		m_childrenNodes.push_back(new TileNode(this, 1, *pTile));
		pTile->reset();

		pTile->setScale(newScale);
		pTile->setType(TILE_F);
		pTile->setDirection(getDir());
		pTile->setOrigin(getTriangle().getVertexA());
		pTile->prePendToCode(B00);
		m_childrenNodes.push_back(new TileNode(this, 2, *pTile));
		pTile->reset();

		pTile->setScale(newScale);
		pTile->setType(TILE_A);
		pTile->setDirection(getDir() + 7);
		pTile->setOrigin(m_childrenNodes[0]->getTriangle().getVertexB());
		pTile->prePendToCode(B10);
		m_childrenNodes.push_back(new TileNode(this, 3, *pTile));
		pTile->reset();
		break;

	case TILE_F:
		pTile->setType(TILE_F);
		pTile->setDirection(getDir() + 12);
		pTile->setOrigin(getTriangle().getVertexC());
		pTile->prePendToCode(B01);
		m_childrenNodes.push_back(new TileNode(this, 0, *pTile));
		pTile->reset();

		pTile->setScale(newScale);
		pTile->setType(TILE_E);
		pTile->setDirection(getDir());
		pTile->setOrigin(m_childrenNodes[0]->getTriangle().getVertexC());
		pTile->prePendToCode(B00);
		m_childrenNodes.push_back(new TileNode(this, 1, *pTile));
		pTile->reset();

		pTile->setScale(newScale);
		pTile->setType(TILE_D);
		pTile->setDirection(getDir() + 8);
		pTile->setOrigin(m_childrenNodes[1]->getTriangle().getVertexC());
		pTile->prePendToCode(B10);
		m_childrenNodes.push_back(new TileNode(this, 2, *pTile));
		pTile->reset();

		pTile->setScale(newScale);
		pTile->setType(TILE_A);
		pTile->setDirection(getDir() + 15);
		pTile->setOrigin(m_childrenNodes[0]->getTriangle().getVertexC());
		pTile->prePendToCode(B01);
		m_childrenNodes.push_back(new TileNode(this, 3, *pTile));
		pTile->reset();
		break;
	}
}

void TileNode::destroyBranch()
{
	size_t childSize = m_childrenNodes.size();
	for(size_t i = 0; i < childSize; ++i)
		delete m_childrenNodes[i];

	m_bLeafNode = true;
	m_childrenNodes.clear();
}

//EOF
